﻿// (c) Copyright Fernando Cerqueira.
// This source is subject to the Microsoft Public License (Ms-PL).
// Please see http://go.microsoft.com/fwlink/?LinkID=131993 for details.
// All other rights reserved.

using System;
using System.Collections.Generic;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Media;
using System.Diagnostics.CodeAnalysis;
using Microsoft.Phone.Controls;

// ReSharper disable CheckNamespace
namespace DevPhone.Controls
// ReSharper restore CheckNamespace
{
    internal class WindowsBoxBase : ContentControl
    {

        #region Create

        private static PhoneApplicationFrame Appframe
        {
            get
            {
                return Application.Current == null ? null : Application.Current.RootVisual as PhoneApplicationFrame;
            }
        }

        internal Grid RootGridHost;

        private bool _lastOrientationPortrait;

        public WindowsBoxBase()
        {
            var rootVisual = Application.Current == null ? null : Application.Current.RootVisual;
            if (rootVisual == null)
            {
                throw new InvalidOperationException("Not found root application.");
            }
            RootGridHost = Application.Current == null ? null : ((FrameworkElement)Application.Current.RootVisual).GetFirstLogicalChildByType<Grid>(false);
            if (RootGridHost == null)
            {
                throw new InvalidOperationException("Not found logical child Grid control.");
            }
            Buttons = new List<WindowsBoxButton>();
            ListenOrientation(true);
        }

        #endregion

        internal virtual void CleanUp()
        {
            ListenOrientation(false);
            RootGridHost = null;
        }

        #region internal DependencyProperties

        internal static readonly DependencyProperty TitleProperty =
            DependencyProperty.Register("Title", typeof(string), typeof(WindowsBoxBase), new PropertyMetadata(null));

        [SuppressMessage("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode", Justification = "Keeping existing implementation.")]
        internal string Title
        {
            get { return (string)GetValue(TitleProperty); }
            set { SetValue(TitleProperty, value); }
        }

        internal static readonly DependencyProperty OverlayBrushProperty =
            DependencyProperty.Register("OverlayBrush", typeof(Brush), typeof(WindowsBoxBase), new PropertyMetadata(null));

        [SuppressMessage("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode", Justification = "Keeping existing implementation.")]
        internal Brush OverlayBrush
        {
            get { return (Brush)GetValue(OverlayBrushProperty); }
            set { SetValue(OverlayBrushProperty, value); }
        }

        internal static readonly DependencyProperty CornerRadiusTopProperty =
            DependencyProperty.Register("CornerRadiusTop", typeof(CornerRadius), typeof(WindowsBoxBase), new PropertyMetadata(null));

        [SuppressMessage("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode", Justification = "Keeping existing implementation.")]
        internal CornerRadius CornerRadiusTop
        {
            get { return (CornerRadius)GetValue(CornerRadiusTopProperty); }
            set { SetValue(CornerRadiusTopProperty, value); }
        }

        internal static readonly DependencyProperty CornerRadiusBottomProperty =
            DependencyProperty.Register("CornerRadiusBottom", typeof(CornerRadius), typeof(WindowsBoxBase), new PropertyMetadata(null));

        [SuppressMessage("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode", Justification = "Keeping existing implementation.")]
        internal CornerRadius CornerRadiusBottom
        {
            get { return (CornerRadius)GetValue(CornerRadiusBottomProperty); }
            set { SetValue(CornerRadiusBottomProperty, value); }
        }

        internal static readonly DependencyProperty ThicknessTitleProperty =
            DependencyProperty.Register("ThicknessTitle", typeof(Thickness), typeof(WindowsBoxBase), new PropertyMetadata(null));

        [SuppressMessage("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode", Justification = "Keeping existing implementation.")]
        internal Thickness ThicknessTitle
        {
            get { return (Thickness)GetValue(ThicknessTitleProperty); }
            set { SetValue(ThicknessTitleProperty, value); }
        }

        internal static readonly DependencyProperty ThicknessMessageProperty =
            DependencyProperty.Register("ThicknessMessage", typeof(Thickness), typeof(WindowsBoxBase), new PropertyMetadata(null));

        [SuppressMessage("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode", Justification = "Keeping existing implementation.")]
        internal Thickness ThicknessMessage
        {
            get { return (Thickness)GetValue(ThicknessMessageProperty); }
            set { SetValue(ThicknessMessageProperty, value); }
        }

        internal static readonly DependencyProperty ThicknessButtonsProperty =
            DependencyProperty.Register("ThicknessButtons", typeof(Thickness), typeof(WindowsBoxBase), new PropertyMetadata(null));

        [SuppressMessage("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode", Justification = "Keeping existing implementation.")]
        internal Thickness ThicknessButtons
        {
            get { return (Thickness)GetValue(ThicknessButtonsProperty); }
            set { SetValue(ThicknessButtonsProperty, value); }
        }

        internal static readonly DependencyProperty MessageBorderBrushProperty =
            DependencyProperty.Register("MessageBorderBrush", typeof(Brush), typeof(WindowsBoxBase), new PropertyMetadata(null));

        [SuppressMessage("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode", Justification = "Keeping existing implementation.")]
        internal Brush MessageBorderBrush
        {
            get { return (Brush)GetValue(MessageBorderBrushProperty); }
            set { SetValue(MessageBorderBrushProperty, value); }
        }

        internal static readonly DependencyProperty TitleForeColorProperty =
            DependencyProperty.Register("TitleForeColor", typeof(Brush), typeof(WindowsBoxBase), new PropertyMetadata(null));

        [SuppressMessage("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode", Justification = "Keeping existing implementation.")]
        internal Brush TitleForeColor
        {
            get { return (Brush)GetValue(TitleForeColorProperty); }
            set { SetValue(TitleForeColorProperty, value); }
        }

        internal static readonly DependencyProperty TitleBackColorProperty =
            DependencyProperty.Register("TitleBackColor", typeof(Brush), typeof(WindowsBoxBase), new PropertyMetadata(null));

        [SuppressMessage("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode", Justification = "Keeping existing implementation.")]
        internal Brush TitleBackColor
        {
            get { return (Brush)GetValue(TitleBackColorProperty); }
            set { SetValue(TitleBackColorProperty, value); }
        }

        internal static readonly DependencyProperty MessageForeColorProperty =
            DependencyProperty.Register("MessageForeColor", typeof(Brush), typeof(WindowsBoxBase), new PropertyMetadata(null));

        [SuppressMessage("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode", Justification = "Keeping existing implementation.")]
        internal Brush MessageForeColor
        {
            get { return (Brush)GetValue(MessageForeColorProperty); }
            set { SetValue(MessageForeColorProperty, value); }
        }

        internal static readonly DependencyProperty MessageBackColorProperty =
            DependencyProperty.Register("MessageBackColor", typeof(Brush), typeof(WindowsBoxBase), new PropertyMetadata(null));

        [SuppressMessage("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode", Justification = "Keeping existing implementation.")]
        internal Brush MessageBackColor
        {
            get { return (Brush)GetValue(MessageBackColorProperty); }
            set { SetValue(MessageBackColorProperty, value); }
        }

        internal static readonly DependencyProperty IconTypeProperty =
            DependencyProperty.Register("IconType", typeof(ImageSource), typeof(WindowsBoxBase), new PropertyMetadata(null));

        [SuppressMessage("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode", Justification = "Keeping existing implementation.")]
        internal ImageSource IconType
        {
            get { return (ImageSource)GetValue(IconTypeProperty); }
            set { SetValue(IconTypeProperty, value); }
        }

        internal static readonly DependencyProperty WindowsMaxHeightProperty =
            DependencyProperty.Register("WindowsMaxHeight", typeof(double), typeof(WindowsBoxBase), new PropertyMetadata(null));

        [SuppressMessage("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode", Justification = "Keeping existing implementation.")]
        internal double WindowsMaxHeight
        {
            get { return (double)GetValue(WindowsMaxHeightProperty); }
            set { SetValue(WindowsMaxHeightProperty, value); }
        }

        internal static readonly DependencyProperty WindowsMaxWidthProperty =
            DependencyProperty.Register("WindowsMaxWidth", typeof(double), typeof(WindowsBoxBase), new PropertyMetadata(null));

        [SuppressMessage("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode", Justification = "Keeping existing implementation.")]
        internal double WindowsMaxWidth
        {
            get { return (double)GetValue(WindowsMaxWidthProperty); }
            set { SetValue(WindowsMaxWidthProperty, value); }
        }

        internal static readonly DependencyProperty WindowsMinWidthProperty =
            DependencyProperty.Register("WindowsMinWidth", typeof(double), typeof(WindowsBoxBase), new PropertyMetadata(null));

        [SuppressMessage("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode", Justification = "Keeping existing implementation.")]
        internal double WindowsMinWidth
        {
            get { return (double)GetValue(WindowsMinWidthProperty); }
            set { SetValue(WindowsMinWidthProperty, value); }
        }

        internal static readonly DependencyProperty AllSelectorsWidthProperty =
            DependencyProperty.Register("AllSelectorsWidth", typeof(double), typeof(WindowsBoxBase), new PropertyMetadata(420.0));

        [SuppressMessage("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode", Justification = "Keeping existing implementation.")]
        internal double AllSelectorsWidth
        {
            get { return (double)GetValue(AllSelectorsWidthProperty); }
            set { SetValue(AllSelectorsWidthProperty, value); }
        }

        #endregion

        #region internal properties

        internal List<WindowsBoxButton> Buttons { get; set; }
        internal WindowsBoxButtonType ButtonType { get; set; }
        internal WindowsBoxIconType ShowIconType { get; set; }
        internal WindowsBoxTypeMessage TypeMessage { get; set; }

        internal Action<WindowsBoxResultEventArgs> ActionClosed { get; set; }
        internal Action<EventArgs> ActionOpen { get; set; }
        internal ImageSource ExternalIcon { get; set; }

        internal bool IsOpen { get; set; }

        #endregion

        #region private properties

        private static bool IsPortrait
        {
            get
            {
                switch (Appframe.Orientation)
                {
                    case PageOrientation.Landscape:
                    case PageOrientation.LandscapeLeft:
                    case PageOrientation.LandscapeRight:
                        return false;
                }
                return true;
            }
        }

        private void ApplyScale()
        {
            WindowsMaxHeight = CurrentWindowsMaxHeight;
            WindowsMaxWidth = CurrentWindowsMaxWidth;
            WindowsMinWidth = CurrentWindowsMinWidth;
        }

        private void AppframeOrientationChanged(object sender, OrientationChangedEventArgs e)
        {
            ApplyScale();
            _lastOrientationPortrait = IsPortrait;
        }

        private void ListenOrientation(bool value)
        {
            if (value)
            {
                _lastOrientationPortrait = IsPortrait;
                WindowsMaxHeight = CurrentWindowsMaxHeight;
                WindowsMaxWidth = CurrentWindowsMaxWidth;
                WindowsMinWidth = CurrentWindowsMinWidth;
                Appframe.OrientationChanged += AppframeOrientationChanged;
            }
            else
            {
                Appframe.OrientationChanged -= AppframeOrientationChanged;
            }
        }

        private double CurrentWindowsMinWidth
        {
            get
            {
                var result = RootGridHost.ActualWidth*0.5;
                if ((_lastOrientationPortrait && !IsPortrait) ||
                    (!_lastOrientationPortrait && IsPortrait))
                {
                    result = RootGridHost.ActualHeight * 0.5;
                }
                return result;
            }
        }

        internal double CurrentWindowsMaxHeight
        {
            get
            {
                var result = RootGridHost.ActualHeight *0.85;
                if ((_lastOrientationPortrait && !IsPortrait) ||
                    (!_lastOrientationPortrait && IsPortrait))
                {
                    result = RootGridHost.ActualWidth *0.85;
                }
                return result;
            }
        }

        private double CurrentWindowsMaxWidth
        {
            get
            {
                if (TypeMessage == WindowsBoxTypeMessage.TimePicker || TypeMessage == WindowsBoxTypeMessage.DatePicker)
                {
                    return 420; // 140 * 3
                }
                var result = RootGridHost.ActualWidth * 0.85;
                if ((_lastOrientationPortrait && !IsPortrait) ||
                    (!_lastOrientationPortrait && IsPortrait))
                {
                    result = RootGridHost.ActualHeight * 0.85;
                }
                return result;
            }
        }

        #endregion

    }
}
